package cn.edu.sgu.www.pms.service.impl;

import cn.edu.sgu.www.pms.consts.CustomMessages;
import cn.edu.sgu.www.pms.consts.Packages;
import cn.edu.sgu.www.pms.dto.PermissionDTO;
import cn.edu.sgu.www.pms.dto.PermissionInitDTO;
import cn.edu.sgu.www.pms.entity.Permission;
import cn.edu.sgu.www.pms.exception.GlobalException;
import cn.edu.sgu.www.pms.mapper.ApplicationMapper;
import cn.edu.sgu.www.pms.mapper.PermissionMapper;
import cn.edu.sgu.www.pms.pager.Pager;
import cn.edu.sgu.www.pms.pager.impl.PermissionPager;
import cn.edu.sgu.www.pms.restful.ResponseCode;
import cn.edu.sgu.www.pms.service.PermissionService;
import cn.edu.sgu.www.pms.util.ObjectUtils;
import cn.edu.sgu.www.pms.util.ResourceScanner;
import cn.edu.sgu.www.pms.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Set;

/**
 * @author 沐雨橙风ιε
 * @version 1.0
 */
@Service
public class PermissionServiceImpl implements PermissionService {

    @Value("${spring.application.name}")
    private String service;

    private final ResourceScanner resourceScanner;
    private final PermissionMapper permissionMapper;
    private final ApplicationMapper applicationMapper;

    @Autowired
    public PermissionServiceImpl(
            ResourceScanner resourceScanner,
            PermissionMapper permissionMapper,
            ApplicationMapper applicationMapper) {
        this.resourceScanner = resourceScanner;
        this.permissionMapper = permissionMapper;
        this.applicationMapper = applicationMapper;
    }

    @Override
    public void init() throws ClassNotFoundException {
        Integer serviceId = applicationMapper.getServiceId(service);

        // 根据应用ID删除权限表的数据
        UpdateWrapper<Permission> updateWrapper = new UpdateWrapper<>();

        updateWrapper.eq("service_id", serviceId);

        permissionMapper.delete(updateWrapper);

        List<Permission> permissions = resourceScanner.scan(Packages.controllerPackage);

        for (Permission permission : permissions) {
            permissionMapper.insert(permission);
        }
    }

    @Override
    public void resources(PermissionInitDTO permissionInitDTO) {
        // 通过应用名查询应用ID
        Integer serviceId = applicationMapper.getServiceId(permissionInitDTO.getService());

        // 根据应用ID删除权限表的数据
        QueryWrapper<Permission> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq("service_id", serviceId);

        permissionMapper.delete(queryWrapper);

        // 批量添加权限
        List<Permission> permissions = permissionInitDTO.getPermissions();

        for (Permission permission : permissions) {
            permission.setServiceId(serviceId);

            permissionMapper.insert(permission);
        }
    }

    @Override
    public void insert(PermissionDTO permissionDTO) {
        Permission permission = toEntity(permissionDTO);

        permissionMapper.insert(permission);
    }

    @Override
    public void deleteByIds(List<String> ids) {
        permissionMapper.deleteBatchIds(ids);
    }

    @Override
    public void updateById(PermissionDTO permissionDTO) {
        ObjectUtils.requireNonNull(permissionDTO.getId(), CustomMessages.ID_NOT_NULL);

        Permission permission = toEntity(permissionDTO);

        permissionMapper.updateById(permission);
    }

    @Override
    public List<Permission> selectList() {
        return permissionMapper.selectList(null);
    }

    @Override
    public List<Permission> selectParent() {
        // 构造查询语句：select id, name from permission where type = 0
        QueryWrapper<Permission> queryWrapper = new QueryWrapper<>();

        // 只查询id和name字段
        queryWrapper.select("id", "name", "service_id");
        // 设置查询条件，where type = 0
        queryWrapper.eq("type", 0);

        return permissionMapper.selectList(queryWrapper);
    }

    @Override
    public Permission selectById(String id) {
        return permissionMapper.selectById(id);
    }

    @Override
    public Page<Permission> selectByPage(PermissionPager pager) {
        QueryWrapper<Permission> wrapper = new QueryWrapper<>();
        Page<Permission> permissionPage = Pager.ofPage(pager);

        wrapper.eq(
                pager.getRemote() != null,
                "remote", pager.getRemote()
        );
        wrapper.eq(
                pager.getServiceId() != null,
                "service_id", pager.getServiceId()
        );
        wrapper.eq(
                StringUtils.isNotEmpty(pager.getParentId()),
                "parent_id", pager.getParentId()
        );

        return permissionMapper.selectPage(permissionPage, wrapper);
    }

    @Override
    public List<Permission> selectPermissions(String service) {
        Integer serviceId = applicationMapper.getServiceId(service);

        if (serviceId == null) {
            throw new GlobalException(ResponseCode.NOT_FOUND, "查询应用失败，应用" + service + "不存在！");
        }

        QueryWrapper<Permission> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq("service_id", serviceId);
        queryWrapper.eq("anonymity", 0);

        return permissionMapper.selectList(queryWrapper);
    }

    @Override
    public Set<String> selectUserPermissions(String username, String service) {
        Integer serviceId = applicationMapper.getServiceId(service);

        if (serviceId == null) {
            throw new GlobalException(ResponseCode.NOT_FOUND, "查询应用失败，应用" + service + "不存在！");
        }

        return permissionMapper.selectUserPermissions(username, serviceId);
    }

    /**
     * DTO转为数据库实体类
     * @param permissionDTO PermissionDTO
     * @return Permission
     */
    private Permission toEntity(PermissionDTO permissionDTO) {
        Permission permission = new Permission();

        permission.setId(permissionDTO.getId());
        permission.setUrl(permissionDTO.getUrl());
        permission.setName(permissionDTO.getName());
        permission.setType(permissionDTO.getType());
        permission.setValue(permissionDTO.getValue());
        permission.setRemote(permissionDTO.getRemote());
        permission.setMethod(permissionDTO.getMethod());
        permission.setParentId(permissionDTO.getParentId());
        permission.setAnonymity(permissionDTO.getAnonymity());
        permission.setServiceId(permissionDTO.getServiceId());

        return permission;
    }

}